package com.smq.chatserver.util;

import com.smq.chatserver.bean.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.CompressionCodecs;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author : 其然乐衣Letitbe
 * @date : 2022/11/12
 */
public class JwtTokenManager {

    /**
     * 用于签名的私钥
     */
    private static final String PRIVATE_KEY = "516Letitbe";

    /**
     * 签发者
     */
    private static final String ISSUER = "Shaomingqing";

    /**
     * 过期时间 1 小时
     */
    private static final long EXPIRATION_ONE_HOUR = 3600L;

    /**
     * 过期时间 1 天
     */
    private static final long EXPIRATION_ONE_DAY = 3600 * 24;

    /**
     * 生成Token
     *
     * @param user token存储的 实体类 信息
     * @return
     */
    public static String createToken(User user, String device, String deviceInfo) {
        Map<String, Object> claims = new HashMap<>();
        // 自定义有效载荷部分, 将User实体类用户名和密码存储
        claims.put("user_id", user.getUserId());
        claims.put("name", user.getName());
        claims.put("mobile", user.getMobile());
        claims.put("portraitUri", user.getPortraitUri());
        claims.put("createTime", user.getCreateTime());
        claims.put("username", user.getUsername());
        claims.put("intro", user.getIntro());
        claims.put("device", device);
        claims.put("deviceInfo", deviceInfo);

        return Jwts.builder()
                // 发证人
                .setIssuer(ISSUER)
                // 有效载荷
                .setClaims(claims)
                // 设定签发时间
                .setIssuedAt(new Date())
                // 设置有效时长
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_ONE_DAY))
                // 使用HS512算法签名，PRIVATE_KEY为签名密钥
                .signWith(SignatureAlgorithm.HS512, PRIVATE_KEY)
                // compressWith() 压缩方法，当载荷过长时可对其进行压缩
                // 可采用jjwt实现的两种压缩方法CompressionCodecs.GZIP和CompressionCodecs.DEFLATE
                .compressWith(CompressionCodecs.GZIP)
                // 生成JWT
                .compact();
    }

    /**
     * 获取token中的User实体类
     *
     * @param token
     * @return
     */
    public static User getUserFromToken(String token) {
        // 获取有效载荷
        Claims claims = getClaimsFromToken(token);
        // 解析token后，从有效载荷取出值
        String s_userId = (String) claims.get("user_id");
        Integer userId = Integer.parseInt(s_userId);
        String name = (String) claims.get("name");
        String mobile = (String) claims.get("mobile");
        String portraitUri = (String) claims.get("portraitUri");
        String s_createTime = (String) claims.get("createTime");
        long createTime = Long.parseLong(s_createTime);
        String username = (String) claims.get("username");
        String intro = (String) claims.get("intro");
        // 封装成User实体类
        return new User(userId, name, mobile, portraitUri, createTime, username, intro);
    }

    /**
     * 获取有效载荷
     *
     * @param token
     * @return
     */
    public static Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    //设定解密私钥
                    .setSigningKey(PRIVATE_KEY)
                    //传入Token
                    .parseClaimsJws(token)
                    //获取载荷类
                    .getBody();
        } catch (Exception e) {
            return null;
        }
        return claims;
    }
}